package helper

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"math/rand"
	"time"
	"github.com/astaxie/beego"
	"encoding/base64"
	"crypto/md5"
	"fmt"
	"github.com/qiniu/api.v7/auth/qbox"
	"github.com/qiniu/api.v7/storage"
	"context"
	"os"
	"regexp"
	"strings"
)
const QINIU_AK = `Md7zpaYMfPtoWQLIPVIkOGSGlkZTNUmfD4IJwp4a`
const QINIU_SK = `IVPxjFf11yq2rx_3yOQ9Ukk76EuoeL85ySLLsZoq`
const QINIU_BUCKET = `pqtest`
const CDN_HOST = "http://image.zhimagk.com"
const EDITOR_IMG_GREP  = `<img[^>]*src="data:image/[^;]+;base64,([^>]+)">`
func MD5Crypt(str string ,halt string)[16]byte{
	first := fmt.Sprintf("%x",md5.Sum([]byte(str + halt)))
	return md5.Sum([]byte(first))
}
func Md5Check(pwd string,input string,halt string) bool{
	first := fmt.Sprintf("%x",md5.Sum([]byte(input + halt)))
	return fmt.Sprintf("%x",md5.Sum([]byte(first))) == pwd
}
func Crypt(str string,halt string)(string,error){
	//md5.Sum([]byte(str+halt))
	key := []byte(halt)
	block, err := aes.NewCipher(key) //选择加密算法
	//beego.Debug(block.BlockSize())
	if err != nil {
		//beego.Debug(err)
		return "", err
	}
	ps := PKCS7Padding([]byte(str), block.BlockSize())
	blockModel := cipher.NewCBCEncrypter(block, key)
	ciphertext := make([]byte, len(ps))
	blockModel.CryptBlocks(ciphertext, ps)
	//beego.Debug(ciphertext)
	return string(Base64Encode(ciphertext)),nil
}

func Decrypt(str string,halt string)  (string, error){
	key := []byte(halt)
	sb := Base64Decode([]byte(str))
	beego.Debug(sb)
	block, err := aes.NewCipher(key) //选择加密算法
	if err != nil {
		return "", err
	}
	blockModel := cipher.NewCBCDecrypter(block, key)
	raw := make([]byte, len(sb))
	blockModel.CryptBlocks(raw, sb)
	raw = PKCS7UnPadding(raw, block.BlockSize())
	return string(raw), nil
}

func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
	//beego.Debug(ciphertext)
	padding := blockSize - len(ciphertext)%blockSize
	padtext := bytes.Repeat([]byte{byte(padding)}, padding)
	return append(ciphertext, padtext...)
}
func PKCS7UnPadding(plantText []byte, blockSize int) []byte {
	length := len(plantText)
	unpadding := int(plantText[length-1])
	return plantText[:(length - unpadding)]
}
var src = rand.NewSource(time.Now().UnixNano())
const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
	letterIdxBits = 6                    // 6 bits to represent a letter index
	letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
	letterIdxMax  = 63 / letterIdxBits   // # of letter indices fitting in 63 bits
)

func RandString(n int) string {
	b := make([]byte, n)
	// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
	for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
		if remain == 0 {
			cache, remain = src.Int63(), letterIdxMax
		}
		if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
			b[i] = letterBytes[idx]
			i--
		}
		cache >>= letterIdxBits
		remain--
	}

	return string(b)
}

func Base64Encode(src []byte) []byte {
	return []byte(base64.StdEncoding.EncodeToString(src))
}

func Base64Decode(src []byte) ([]byte) {
	//return Base64Coder.DecodeString(string(src))
	de,err := base64.StdEncoding.DecodeString(string(src))
	if err != nil {
		beego.Error("Wrong base64 decode string for :" + string(src))
	}
	return de
}
func UploadEditorImageContent(content string) string{
	reg,_ := regexp.Compile(EDITOR_IMG_GREP)
	//replace image to qiniu link
	matched := reg.FindAllStringSubmatch(content,-1)
	for _,c := range matched {
		imgContent,_ := base64.StdEncoding.DecodeString(string(c[1]))
		dest := fmt.Sprintf(`<img src="%s/%s"/>`,CDN_HOST,UploadImageToQiniu(SaveImageDataToFile(imgContent)))
		content = strings.Replace(content,string(c[0]),dest,1)
	}
	beego.Info(content)
	return content
}
func SaveImageDataToFile(bin []byte) string{
	localFile := fmt.Sprintf("/tmp/%x.png",md5.Sum(bin))
	fh,err := os.Create(localFile)
	if err == nil{
		defer fh.Close()
		fh.Write(bin)
		//beego.Warning(imgData)
	} else{
		beego.Error(err.Error())
	}
	return localFile
}
func UploadImageToQiniu(path string) string{
	//qiniu_ak := "YICBiD6x7yX_UfxlzWrU3x0UuCLmWC-L_1rt86su"
	//qiniu_sk := "Pn1NBs8-Ev-y2OhGNP30GPtmUnP0yYeWRHce7-Cc"
	filename := fmt.Sprintf("%x", md5.Sum([]byte(path)))
	localFile := path
	key := filename+".png"
	putPolicy := storage.PutPolicy{
		Scope: QINIU_BUCKET,
	}
	mac := qbox.NewMac(QINIU_AK, QINIU_SK)
	upToken := putPolicy.UploadToken(mac)
	cfg := storage.Config{}
	// 空间对应的机房
	cfg.Zone = &storage.ZoneHuanan
	// 是否使用https域名
	cfg.UseHTTPS = false
	// 上传是否使用CDN上传加速
	cfg.UseCdnDomains = false
	// 构建表单上传的对象
	formUploader := storage.NewFormUploader(&cfg)
	ret := storage.PutRet{}
	// 可选配置
	putExtra := storage.PutExtra{
		Params: map[string]string{
			"x:name": "avatar logo",
		},
	}
	err := formUploader.PutFile(context.Background(), &ret, upToken, key, localFile, &putExtra)
	if err != nil {
		//fmt.Println(err)
		beego.Error(err.Error())
		//return
	}
	return key
}

func UnmarshalPointSettingJson( jsonstr string ) []map[string]string {
	var r  []map[string]string
	if jsonstr == `{}` {
		return r
	}
	ts := strings.TrimLeft(jsonstr,"{")
	ts = strings.TrimRight(ts,"}")
	ss := strings.Split(ts,",")
	for _,s := range ss {
		os := strings.Split(s,":")
		rr := make(map[string]string)
		rr[strings.Trim(os[0],`"`)] = strings.Trim(os[1],`"`)
		r = append(r,rr)
	}
	return r
}

